package com.stardata.liangshisq.tcslmon.interceptor;

import com.stardata.liangshisq.tcslmon.annotation.IgnoreAuth;
import com.stardata.liangshisq.tcslmon.entity.DbiEmp;
import com.stardata.liangshisq.tcslmon.entity.UserToken;
import com.stardata.liangshisq.tcslmon.service.DbiEmpService;
import com.stardata.liangshisq.tcslmon.service.SysParameterService;
import com.stardata.liangshisq.tcslmon.service.TokenService;
import com.stardata.liangshisq.tcslmon.util.ApiRRException;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDate;
import java.time.LocalDateTime;

/**
 * 权限(Token)验证
 *
 * @author lipengjun
 * @email 939961241@qq.com
 * @gitee https://gitee.com/fuyang_lipengjun/platform
 * @date 2017-03-23 15:38
 */
@Component
@AllArgsConstructor
public class AuthorizationInterceptor extends HandlerInterceptorAdapter {
    private final TokenService tokenService;
    private final DbiEmpService empService;
    private final SysParameterService parameterService;

    public static final String LOGIN_USER_KEY = "LOGIN_USER_KEY";
    public static final String LOGIN_TOKEN_KEY = "X-Liangshisq-Token";


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, @NotNull Object handler) {

        //支持跨域请求
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with,"+LOGIN_TOKEN_KEY+",X-URL-PATH");
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));

        IgnoreAuth annotation;
        if (handler instanceof HandlerMethod) {
            annotation = ((HandlerMethod) handler).getMethodAnnotation(IgnoreAuth.class);
        } else {
            return true;
        }

        //如果有@IgnoreAuth注解，则不验证token
        if (annotation != null) {
            return true;
        }

        //从header中获取token
        String token = request.getHeader(LOGIN_TOKEN_KEY);
        //如果header中不存在token，则从参数中获取token
        if (StringUtils.isBlank(token)) {
            token = request.getParameter(LOGIN_TOKEN_KEY);
        }

        //token为空
        if (StringUtils.isBlank(token)) {
            throw new ApiRRException(HttpStatus.UNAUTHORIZED, "请先登录");
        }

        //查询token信息
        UserToken userToken = tokenService.getByToken(token);
        if (userToken == null || userToken.getExpireTime().compareTo(LocalDateTime.now()) < 0) {
            throw new ApiRRException(HttpStatus.UNAUTHORIZED, "请重新登录");
        }

        //有可能该用户token存在，但用户数据在后台已被逻辑删除
        Long userId = userToken.getUserId();
        DbiEmp user = empService.getById(userId);
        if (null == user) {
            throw new ApiRRException(HttpStatus.UNAUTHORIZED, "请重新登录");
        }

        //设置user到request里，方便后续使用
        request.setAttribute(LOGIN_USER_KEY, user);

        try{
            LocalDate today =  LocalDate.now();
            String expireDateStr = parameterService.getByCode("evaluate_expired_date");
            if (!StringUtils.isEmpty(expireDateStr)) {
                String[] sarr = expireDateStr.split("-");
                int year = Integer.parseInt(sarr[0]);
                int month = Integer.parseInt(sarr[1]);
                int day = Integer.parseInt(sarr[2]);
                LocalDate expiredDate = LocalDate.of(year, month, day);
                if (today.isAfter(expiredDate)) {
                    throw new ApiRRException(HttpStatus.UNAUTHORIZED, "软件试用已过期！");
                }
            }
        } catch (Exception ignored){}

        return true;
    }
}
